package com.ruoyi.web.admin.data;

import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysDevice;
import com.ruoyi.system.service.ISysDeviceService;
import com.ruoyi.web.admin.data.utils.AESUtils;
import io.netty.channel.Channel;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 设备连接管理类
 * 统一管理TCP和WebSocket连接
 *
 * @author 10100
 */
@Component
public class DeviceSocketManager {

    private static final Logger log = LoggerFactory.getLogger(DeviceSocketManager.class);

    private static final ConcurrentHashMap<String, DeviceChannelInfo> CLIENTS = new ConcurrentHashMap<>();

    private static ISysDeviceService sysDeviceService = null;

    @PostConstruct
    private void init() {
        sysDeviceService = SpringUtils.getBean(ISysDeviceService.class);
    }

    public static void addClient(String deviceId, DeviceChannelInfo channelInfo) {
        CLIENTS.put(deviceId, channelInfo);
    }

    public static void removeClient(String deviceId) {
        SysDevice device = sysDeviceService.selectSysDeviceByeIdentifier(deviceId);
        if (device != null) {

            /*此处过于频繁触发，暂时忽略，仅依赖定时任务*/
            /*device.setConnectionStatus("0");*/
            /*sysDeviceService.updateSysDevice(device);*/
            /*sysDeviceCollectRecordService.insertRecord(device, "CONNECTION_STATUS", "0", "0离线 1在线");*/
            log.info("设备[{}]状态已更新为离线", deviceId);
        } else {
            // 设备不存在，创建新设备记录
            log.info("设备[{}]不存在，已离线", deviceId);
        }
        CLIENTS.remove(deviceId);
    }

    public static DeviceChannelInfo getClient(String deviceId) {
        return CLIENTS.get(deviceId);
    }

    public static List<String> getAllClientsKey() {
        return new ArrayList<>(CLIENTS.keySet());

    }

    public static boolean isDeviceOnline(String deviceId) {
        DeviceChannelInfo channelInfo = CLIENTS.get(deviceId);
        Channel channel = channelInfo == null ? null : channelInfo.getChannel();
        return channel != null && channel.isActive();
    }

    /**
     * 平台主动下发消息
     * 优先尝试WebSocket连接，如果WebSocket连接不可用，则尝试TCP连接
     *
     * @param deviceId 设备ID
     * @param message  消息内容
     * @return 是否发送成功
     */
    public static boolean sendToDevice(String deviceId, String message) {
        DeviceChannelInfo channelInfo = CLIENTS.get(deviceId);
        Channel channel = channelInfo == null ? null : channelInfo.getChannel();

        if (channel != null && channel.isActive()) {
            String encryptMsg = AESUtils.encrypt(message);
            if (StringUtils.isEmpty(encryptMsg)) {
                throw new RuntimeException("数据加密失败，取消发送消息");
            }
            channel.writeAndFlush(encryptMsg);
        } else {
            log.error("设备[{}]不在线，无法发送消息", deviceId);
        }
        return true;
    }

    /**
     * 平台主动下发消息
     * 优先尝试WebSocket连接，如果WebSocket连接不可用，则尝试TCP连接
     *
     * @param message 消息内容
     */
    public static void broadcastMessage(String message) {
        String encryptMsg = AESUtils.encrypt(message);
        if (StringUtils.isEmpty(encryptMsg)) {
            throw new RuntimeException("数据加密失败，取消发送消息");
        }

        CLIENTS.forEachKey(1, deviceId -> {
            DeviceChannelInfo channelInfo = CLIENTS.get(deviceId);
            Channel channel = channelInfo == null ? null : channelInfo.getChannel();
            if (channel != null && channel.isActive()) {
                channel.writeAndFlush(encryptMsg);
            } else {
                log.warn("设备[{}]不在线，无法发送消息", deviceId);
            }
        });
    }
}